package net.bac.sbe.web.sonar.server.report.wrapper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletContext;

import net.bac.sbe.common.api.view.SonarItemValidationView;
import net.bac.sbe.common.api.view.SonarItemView;
import net.bac.sbe.common.api.view.SonarValidationView;
import net.bac.sbe.common.sonar.validation.SbeSonarMetricsValidator;
import net.bac.sbe.svn.view.SbeSVNDiffItemView;
import net.bac.sbe.web.report.ReportFormat;
import net.bac.sbe.web.report.ReportGenerator;
import net.bac.sbe.web.report.sonarfiltered.SonarInformationReport;
import net.bac.sbe.web.report.sonarfiltered.view.MetricView;
import net.bac.sbe.web.sonar.client.view.ReportView;
import net.bac.sbe.web.sonar.server.SVNServiceWrapper;
import net.bac.sbe.web.sonar.server.dev.utils.xml.applications.ApplicationsConfig;
import net.bac.sbe.web.sonar.server.dev.utils.xml.applications.ModuleType;

import com.google.inject.Inject;

public class SonarInformationReportServiceWrapper {


	@Inject
	private SVNServiceWrapper svnWrapper;

	@Inject
	private SbeSonarMetricsValidator sonarMetricsValidator;

	@Inject
	@SonarInformationReport
	private ReportGenerator reportGenerator;

	public void setReportGenerator(ReportGenerator reportGenerator) {
		this.reportGenerator = reportGenerator;
	}

	public void setSonarMetricsValidator(
			SbeSonarMetricsValidator sonarMetricsValidator) {
		this.sonarMetricsValidator = sonarMetricsValidator;
	}


	public void setSvnWrapper(SVNServiceWrapper svnWrapper) {
		this.svnWrapper = svnWrapper;
	}


	public ReportView generateSonarFilteredReport(String projectId,
			String projectAnalyst, String projectDescription, List<String> repositories, ServletContext context, String repToCompare) {

		SonarValidationView data = getSonarFilteredReportData(projectId, repositories, repToCompare);

		Map<String, List<Object>> primaryDataSet = new HashMap<String, List<Object>>();
		Map<String, List<Object>> summaryDataSet = new HashMap<String, List<Object>>();

		primaryDataSet.put("PACKAGE", new ArrayList<Object>(data.getItems().size()));
		primaryDataSet.put("ITEM", new ArrayList<Object>(data.getItems().size()));
		primaryDataSet.put("METRICS", new ArrayList<Object>(data.getItems().size()));
		primaryDataSet.put("IS_NEW", new ArrayList<Object>(data.getItems().size()));
		primaryDataSet.put("IS_VALID_ITEM", new ArrayList<Object>(data.getItems().size()));
		primaryDataSet.put("APPLICATION", new ArrayList<Object>(data.getItems().size()));
		primaryDataSet.put("MODULE", new ArrayList<Object>(data.getItems().size()));

		summaryDataSet.put("INDICATOR", new ArrayList<Object>(data.getIndicatorGrades().size()));
		summaryDataSet.put("GRADE", new ArrayList<Object>(data.getIndicatorGrades().size()));

		for (SonarItemValidationView item : data.getItems()) {

			primaryDataSet.get("PACKAGE").add(item.getItemPackage());
			primaryDataSet.get("ITEM").add(item.getItemName());

			List<MetricView> metricList = new ArrayList<MetricView>(item.getMetrics().size());
			for (Entry<String, Double> metric : item.getMetrics().entrySet()) {
				String validationComment = item.getValidationComments().get(metric.getKey());
				MetricView metricView = new MetricView(
						metric.getKey(),
						metric.getValue(),
						null==item.getBaseLineMetrics().get(metric.getKey())?0D:item.getBaseLineMetrics().get(metric.getKey()),
						null==validationComment?"":validationComment);
				metricList.add(metricView);
			}

			primaryDataSet.get("METRICS").add(metricList);
			primaryDataSet.get("IS_NEW").add(item.isNew()?"Si":"No");
			primaryDataSet.get("IS_VALID_ITEM").add(item.pasesValidation()?"Si":"No");
			primaryDataSet.get("APPLICATION").add(item.getArtifactId());
			primaryDataSet.get("MODULE").add(item.getModule());
		}


		for (Entry<String, Double> indicator : data.getIndicatorGrades().entrySet()) {
			summaryDataSet.get("INDICATOR").add(indicator.getKey());
			summaryDataSet.get("GRADE").add(indicator.getValue());
		}



		ReportView reportView = getSonarFilteredReportView(projectId);

		String reportAbsolutePath = context.getRealPath(reportView.getReportURLForDownload());

		HashMap<String, Object> reportParameters = new HashMap<String, Object>(8);


		reportParameters.put(ReportGenerator.PROJECT_NAME_KEY, projectDescription);
		reportParameters.put(ReportGenerator.PROJECT_ID_KEY, projectId);
		reportParameters.put(ReportGenerator.ANALYST_NAME_KEY, projectAnalyst);
		reportParameters.put(ReportGenerator.REPORT_DATA_SET_1, primaryDataSet);
		reportParameters.put(ReportGenerator.REPORT_DATA_SET_2, summaryDataSet);
		reportParameters.put(ReportGenerator.REPORT_FORMAT_KEY, ReportFormat.PDF);
		reportParameters.put(ReportGenerator.REPORT_ABSOLUTE_PATH_KEY, reportAbsolutePath);
		reportParameters.put(ReportGenerator.ITEM_QUANTITY_KEY, primaryDataSet.get("PACKAGE").size());

		reportGenerator.generateReport(reportParameters);

		return reportView;
	}


	private ReportView getSonarFilteredReportView(String projectName) {
		ReportView reportView = new ReportView();
		reportView.setReportName("Reporte de Sonar - ".concat(projectName)
				.concat(".pdf"));
		reportView
				.setReportContextualURL("reports/sonarReports");
		return reportView;
	}



	private SonarValidationView getSonarFilteredReportData(String projectName, List<String> repositories, String repToCompare) {

		List<SbeSVNDiffItemView> changes = svnWrapper.getModifiedItems(projectName, repositories, repToCompare);

		List<SonarItemView> sonarData = new ArrayList<SonarItemView>();

		for (SbeSVNDiffItemView sbeSVNDiffItemView : changes) {
			if (' ' != sbeSVNDiffItemView.getModificationCode()
					&& 'D' != sbeSVNDiffItemView.getModificationCode()
					&& sbeSVNDiffItemView.isFile()
					&& sbeSVNDiffItemView.isFile()
					&& "java".equalsIgnoreCase(sbeSVNDiffItemView
							.getExtension())) {

				ModuleType moduleConfig = ApplicationsConfig.getInstance()
						.getModuleConfigByRegularExpression(
								sbeSVNDiffItemView.getPath());
				if (null != moduleConfig.getArtifactId() && !"".equals(moduleConfig.getArtifactId())) {
					SonarItemView item = new SonarItemView();

					item.setArtifactId(moduleConfig.getArtifactId());
					item.setItemName(getItemNameForSonarReport(sbeSVNDiffItemView));
					item.setItemType(sbeSVNDiffItemView.getExtension());
					item.setBranchId(projectName);
					item.setModule(moduleConfig.getName());
					item.setItemPackage(getJavaPackageForModule(sbeSVNDiffItemView, moduleConfig));
					if (sbeSVNDiffItemView.getModificationCode() == 'A') {
						item.setNew(true);
					} else {
						item.setNew(false);
					}
					sonarData.add(item);
				}
			}
		}

		return sonarMetricsValidator.validateMetrics(sonarData);
	}

	private String getItemNameForSonarReport(
			SbeSVNDiffItemView sbeSVNDiffItemView) {
		return sbeSVNDiffItemView.getItem().substring(0,sbeSVNDiffItemView.getItem().lastIndexOf('.'));
	}

	private String getJavaPackageForModule(SbeSVNDiffItemView sbeSVNDiffItemView, ModuleType moduleConfig) {

		String [] sections = sbeSVNDiffItemView.getFolder().split(moduleConfig.getSourcePath());
		String javaPackage = sections[sections.length-1];
		javaPackage = javaPackage.substring(0, javaPackage.lastIndexOf('/')).replace('/', '.');
		return javaPackage;
	}
}
